
package hk.ces.oxfam.patch;

import hk.ces.oxfam.patch.config.Config;
import hk.ces.oxfam.patch.config.Setting;
import hk.ces.oxfam.patch.connection.ConnectionUtil;
import hk.ces.oxfam.patch.db.result.ExcuteStatus;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;

/**
 *
 * @author ReutyCheng
 */
public class DBPatchEngine
{
  private final Collection<DBPatch> patchs = new ArrayList<DBPatch>();

  public DBPatchEngine()
  {
  }

  public void add(DBPatch patch)
  {
    if (patch != null)
    {
      patchs.add(patch);
    }
  }

  public void runAll()
  {
    Connection connection = ConnectionUtil.openConnection();
    if (connection == null)
    {
      throw new RuntimeException("Connection is null. Can't run patchs");
    }

    Logger.getLogger(this.getClass()).debug("DB Patch for : " + Config.getCurrentConfigServer() + "\n==================================================================================================================");
    for (DBPatch patch : patchs)
    {
      DBPatchSession.put(DBPatchSession.CURRENT_PATCH, patch.getClass());
      
      Logger.getLogger(this.getClass()).debug("Start DBPatch : " + patch.getName() + "\n==================================================================================================================");
      try
      {
        connection.setAutoCommit(false);
        patch.patch(connection);

        ExcuteStatus status = ConnectionUtil.excute(connection);

        switch (status)
        {
          case WAIT_TO_ENGINE:
            if (Setting.get().booleanValue.getValue(Setting.ENABLED_COMMIT))
            {
              ConnectionUtil.commit(connection);
              Logger.getLogger(ConnectionUtil.class.getClass()).fatal("Commit Patch!");
            }
            else
            {
              ConnectionUtil.rollback(connection);
              Logger.getLogger(ConnectionUtil.class.getClass()).fatal("User have NOT permission to commit Patch. rollback transactions. You should enable it in setting.properties");
            }
            break;
          case COMMIT:
            Logger.getLogger(ConnectionUtil.class.getClass()).fatal("Commit Patch!");
            break;
          case ROLLBACK:
            Logger.getLogger(ConnectionUtil.class.getClass()).fatal("User have NOT permission to commit Patch. rollback transactions. You should enable it in setting.properties");
            break;
          case EXCEPTION:
            Logger.getLogger(ConnectionUtil.class.getClass()).fatal("!! Error Occur. Rollback all transactions !!");
            break;
          default:
            Logger.getLogger(ConnectionUtil.class.getClass()).fatal("!! Undefind Action !!");
            break;
        }
      }
      catch (SQLException ex)
      {
        Logger.getLogger(this.getClass()).error("!! Error Occur. Rollback all transactions !!", ex);
      }
      finally
      {
        Logger.getLogger(this.getClass()).debug("End DBPatch : " + patch.getName() + "\n==================================================================================================================");
        DBPatchSession.clear();
      }
    }

    ConnectionUtil.closeConnection(connection);
  }
}
